Mysql索引入门
什么是索引
索引用于快速找出在某个列中有一特定值的行
索引类型
大多数MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)在B树中存储。只是空间列类型的索引使用R-树,并且MEMORY表还支持hash索引
索引越多越好?
- 数据的变更(增删改)都需要维护索引,因此更多的索引意味着更多的维护成本
- 更多的索引意味着也需要更多的空间 (一本100页的书,却有50页目录?)
- 过小的表,建索引可能会更慢
- 频繁写入影响性能
使用索引
1
2
3like 'xxx%' -- 可以用索引
Like '%xxx%' -- 不能用索引
like '%xxx' -- 不能用索引1
2<,<=,=,>,>=,BETWEEN,IN -- 可以用索引
<>,not in ,!=则不行 -- 不能用索引1
2
3SELECT `sname` FROM `t_stu` WHERE `age`=20; -- 会使用索引
SELECT `sname` FROM `t_stu` WHERE `age`+10=30; -- 不会使用索引!!因为所有索引列参与了计算
SELECT `sname` FROM `t_stu` WHERE `age`=30-10; -- 会使用索引1
2SELECT `sname` FROM `stu` WHERE concat(`sname`,'abc') ='Jaskeyabc'; -- 不会使用索引,因为使用了函数运算,原理与上面相同
SELECT `sname` FROM `stu` WHERE `sname` =concat('Jaskey','abc'); -- 会使用索引1
2
3
4
5select * from dept where dname='jaskey' or loc='bj' or deptno=45 --如果条件中有or,即使其中有条件带索引也不会使用。换言之,就是要求使用的所有字段,都必须建立索引
可以通过union来替换or
select * from dept where dname='jaskey' union
select * from dept where loc='bj' union
select * from dept where deptno=45什么样的字段适合建索引
- 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
- 较频繁的作为查询条件的字段应该创建索引
什么时候用复合索引
where a = x and b =xx 是建立索引a,索引b,索引ab,索引ba?
看区分度
最左前缀原则
复合索引(a,b,c),可以用到索引的情况是
where a=x and b=x and c=x
where a=x and b=x
where a=x
其余where条件都不能用到索引
order by 索引
单独使用order by是不能用索引的,需要配合limit
where+orderby时需要加复合索引,比如where a=x order by b,c需要加(a,b,c)索引
当有多个索引,选择哪个
mysql 会自动选择返回集合小的索引
不要过早优化,除非仔细分析
explain工具
Case Study
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49CREATE TABLEt_cms_comment` (
id bigint(20) NOT NULL AUTO_INCREMENT,
content text,
create_time timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
platform_id int(11) DEFAULT NULL,
update_time timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
target_type varchar(30) DEFAULT NULL,
target_id bigint(20) DEFAULT NULL,
content_type varchar(30) DEFAULT NULL,
interaction_type varchar(30) DEFAULT NULL,
user_id bigint(20) DEFAULT NULL,
variety varchar(255) DEFAULT NULL,
variety_id bigint(20) DEFAULT NULL,
create_user bigint(20) DEFAULT NULL,
deleted int(11) DEFAULT NULL,
update_user bigint(20) DEFAULT NULL,
audit_state varchar(30) DEFAULT NULL,
author_type varchar(30) DEFAULT NULL,
is_top bit(1) DEFAULT NULL,
top_priority bigint(20) DEFAULT NULL,
audit_user bigint(20) DEFAULT NULL,
audit_time timestamp NULL DEFAULT NULL,
re_audit_user bigint(20) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;select * from t_cms_comment where create_time < ‘2017-11-09 10:00:00’ and variety_id=5 and variety=’studio’ order by top_priority desc ,create_time desc, id desc limit 200 — 怎么加索引?
- where create_time < ‘2017-11-09 10:00:00’ and variety_id=5 and variety=’studio’
- order by : top_priority desc ,create_time desc, id desc
- where + order by 复合索引,如果不行,优先考虑对sort建立索引,因为sort比较耗性能
- 可能索引:(top_priority+create_time+id), (create_time+varierty_id),(variety_id)